home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / Snippets / Testing & Debugging / Audit / Src / AuditDCMD.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-21  |  10.9 KB  |  470 lines  |  [TEXT/MPS ]

  1. /*
  2.  * AuditDCMD.c
  3.  * Copyright © 1992-93 Apple Computer Inc. All Rights Reserved.
  4.  * Programmed by Martin Minow,
  5.  *    Internet:    minow@apple.com
  6.  *    AppleLink:    MINOW
  7.  * Version of January 4, 1993
  8.  *
  9.  * Provide formatted access to a Audit from within MacsBug.
  10.  *
  11.  * The following commands are supported:
  12.  *
  13.  *    Audit NAME on            Turn logging on for this log
  14.  *    Audit NAME off            Turn logging off
  15.  *    Audit NAME write            Display the entire log (including
  16.  *                                free areas that contain "real" data).
  17.  * Note that the log area must already have been created.
  18.  *
  19.  * AuditDCMD is built by the following commands (they are best
  20.  * placed in a suitable Makefile). BuildDCMD and the libraries
  21.  * are distributed with MacsBug. This sequence assumes MPW 3.2
  22.  * + cut here
  23.         C                                    ∂
  24.             -i {DCMDIncludes}                ∂
  25.             -o AuditDCMD.c.o                ∂
  26.             AuditDCMD.c
  27.         C                                    ∂
  28.             -i {DCMDIncludes}                ∂
  29.             -o AuditEntryFormat.c.o            ∂
  30.             AuditEntryFormat.c
  31.         Link                                ∂
  32.             -o Audit                        ∂
  33.             {DCMDLibraries}dcmdGlue.a.o        ∂
  34.             AuditDCMD.c.o                    ∂
  35.             AuditEntryFormat.c.o            ∂
  36.             "{Libraries}"Runtime.o            ∂
  37.             "{Libraries}"Interface.o
  38.         {DCMD}BuildDcmd Audit 1000
  39.         Echo 'include "Audit";'                ∂
  40.             | Rez -a -o "{systemFolder}Debugger Prefs"
  41.  * - to here
  42.  *    Note:  Be sure to link dcmdGlue.a.o first.  The files in the
  43.  *    dcmd libraries folder are distributed with Macsbug.
  44.  */
  45. #include <Types.h>
  46. /*
  47.  * AuditDCMD.c
  48.  * Copyright © 1992-93 Apple Computer Inc. All Rights Reserved.
  49.  * Programmed by Martin Minow,
  50.  *    Internet:    minow@apple.com
  51.  *    AppleLink:    MINOW
  52.  * Version of January 14, 1993
  53.  *
  54.  * Edit History
  55.  *    93.01.09 MM        First public release
  56.  *    93.01.14 MM        Think and MPW generate different record sizes;
  57.  *                    a disaster if you create an Audit Record under
  58.  *                    Think and call Audit compiled under MPW. Also
  59.  *                    added a test for record sizes and included
  60.  *                    record size information in the AuditRecord.
  61.  *
  62.  * This is a MacsBug DCMD that can display AuditRecord contents.
  63.  */
  64. #include <Traps.h>
  65. #include <GestaltEqu.h>
  66. #include <Memory.h>
  67. #include "Audit.h"
  68. /*
  69.  * This file should be copied from the MacsBug distribution. Note
  70.  * that we have our own display routines: only dcmdDrawString,
  71.  * dcmdDrawLine, and dcmdDrawText are used.
  72.  */
  73. #include "dcmd.h"
  74. /*
  75.  * The version id's are defined as (majorVersion << 8) | minorVersion
  76.  */
  77. #define kAuditDCMDEarliestVersion    ((1 << 8) | 1)
  78. #define kAuditDCMDLatestVersion        ((1 << 8) | 1)
  79.  
  80. #ifndef TRUE
  81. #define TRUE    1
  82. #define FALSE    0
  83. #endif
  84. /*
  85.  * These values must match values in Audit.c
  86.  */
  87. #define kAuditMagicHeaderSize    7            /* Size in longwords            */
  88. #define kAuditMagicHeader_0        0x4E560000    /* First word in Gestalt result    */
  89.  
  90. #define LOG        (*auditPtr)
  91. #define ENTRY    (*entryPtr)
  92.  
  93. AuditPtr                DCMDGetAuditPtr(
  94.         OSType                        gestaltSelector
  95.     );
  96. void                    DumpAudit(
  97.         register AuditPtr            auditPtr
  98.     );
  99. void                    DumpAuditEntry(
  100.         register AuditPtr            auditPtr,
  101.         register AuditEntryPtr        entryPtr
  102.     );
  103. Boolean                    CompareString(
  104.         const StringPtr                a,
  105.         const StringPtr                b
  106.     );
  107. void                    PutUnsignedLeadingZeros(
  108.         unsigned long                value,
  109.         short                        digits
  110.     );
  111. void                    PutHexLeadingZeros(
  112.         unsigned long                value,
  113.         short                        digits
  114.     );
  115. void                    PutUnsigned(
  116.         unsigned long                value
  117.     );
  118. void                    PutSigned(
  119.         signed long                    value
  120.     );
  121. void                    PutOSType(
  122.         OSType                        datum
  123.     );
  124. void                    PutChar(
  125.         unsigned char                datum
  126.     );
  127. void                    PutPascalString(
  128.         const StringPtr                datum
  129.     );
  130. pascal void                CommandEntry(
  131.         dcmdBlock            *paramPtr
  132.     );
  133. pascal void                dcmdSwapWorlds(void);
  134. void                    PutLine(void);
  135.  
  136. pascal void
  137. CommandEntry(
  138.         dcmdBlock            *paramPtr
  139.     )
  140. {
  141.         register AuditPtr        auditPtr;
  142.         Str255                    formatString;
  143.         OSType                    gestaltSelector;
  144.         Boolean                    oldEnableState;
  145.         
  146.         switch (paramPtr->request) {
  147.         case dcmdDoIt:        
  148.             dcmdSwapWorlds();                /* TMON needs this        */
  149.             (void) dcmdGetNextParameter(formatString);
  150.             while (formatString[0] < 4)
  151.                 formatString[++formatString[0]] = ' ';
  152.             if (formatString[0] == (4 + 2)
  153.                 && formatString[1] == '\''
  154.                 && formatString[5] == '\'')
  155.                 BlockMove(&formatString[2], &gestaltSelector, 4);
  156.             else {
  157.                 BlockMove(&formatString[1], &gestaltSelector, 4);
  158.             }
  159.             PutPascalString("\pAudit ");
  160.             PutOSType(gestaltSelector);
  161.             PutLine();
  162.             auditPtr = DCMDGetAuditPtr(gestaltSelector);
  163.             if (auditPtr == NULL) {
  164.                 dcmdDrawLine("\pUndefined audit area");
  165.                 goto drawHelp;
  166.             }
  167.             else {
  168.                 PutPascalString("\pAudit area at ");
  169.                 PutHexLeadingZeros((unsigned long) auditPtr, 8);
  170.                 PutLine();
  171.                 oldEnableState = (LOG.flags & kAuditEnabledMask) != 0;
  172.                 (void) dcmdGetNextParameter(formatString);
  173.                 if (CompareString("\pON", formatString)) {
  174.                     LOG.flags |= kAuditEnabledMask;
  175.                     PutPascalString("\pAuditing enabled, was ");
  176.                     goto turnOffExit;
  177.                 }
  178.                 else if (CompareString("\pOFF", formatString)) {
  179.                     LOG.flags &= ~kAuditEnabledMask;
  180.                     PutPascalString("\pAuditing disabled, was ");
  181. turnOffExit:        PutPascalString((oldEnableState)
  182.                         ? "\penabled" : "\pdisabled");
  183.                     PutLine();
  184.                 }
  185.                 else if (CompareString("\pWRITE", formatString)
  186.                       || formatString[0] == 0)
  187.                     DumpAudit(auditPtr);
  188.                 else {
  189.                     dcmdDrawLine("\pUnknown Audit command.");
  190.                     goto drawHelp;
  191.                 }
  192.             }
  193.             dcmdSwapWorlds();                /* TMON needs this        */
  194.             break;
  195.         case dcmdHelp:
  196.             dcmdDrawLine("\pAudit formats Audit record area.");
  197. drawHelp:    dcmdDrawLine("\pFormat: Audit NAME on | Audit NAME off"
  198.                 " | Audit NAME write");
  199.             dcmdDrawLine("\pWhere NAME is the Audit Gestalt identifier.");
  200.             dcmdDrawLine("\p\"Write\" is assumed if no command is given.");
  201.             break;
  202.         }
  203. }
  204.  
  205. AuditPtr
  206. DCMDGetAuditPtr(
  207.         OSType            gestaltSelector
  208.     )
  209. {
  210.         auto long                    gestaltResponse;
  211.         register AuditPtr            auditPtr;
  212.  
  213.         auditPtr = NULL;
  214.         if (Gestalt(gestaltSelector, &gestaltResponse) != noErr)
  215.             dcmdDrawLine("\pNo such AuditRecord");
  216.         else if (gestaltResponse == 0
  217.               || (gestaltResponse & 0x3) != 0)
  218.              dcmdDrawLine("\pThis is not an AuditRecord (wrong Gestalt value)");
  219.         else {
  220.             auditPtr = (AuditPtr) gestaltResponse;
  221.             if (((unsigned long *) auditPtr)[-kAuditMagicHeaderSize]
  222.                     != kAuditMagicHeader_0) {
  223.                 dcmdDrawLine("\pThis is not an AuditRecord (wrong header)");
  224.                 auditPtr = NULL;
  225.             }
  226.             else if (LOG.version.u.low < kAuditDCMDEarliestVersion) {
  227.                 dcmdDrawLine("\pThis AuditRecord release is earlier than our minimum");
  228.                 auditPtr = NULL;
  229.             }
  230.             else if (LOG.version.u.high > kAuditDCMDLatestVersion) {
  231.                 dcmdDrawLine("\pThis AuditRecord release is later than our maximum");
  232.                 auditPtr = NULL;
  233.             }
  234.             else if (LOG.recordSize != kAuditRecordSize) {
  235.                 dcmdDrawLine("\pRecord size mismatch");
  236.                 PutPascalString("\pRecord size mismatch, expecting ");
  237.                 PutHexLeadingZeros(kAuditRecordSize, 8);
  238.                 PutPascalString(", got ");
  239.                 PutHexLeadingZeros(LOG.recordSize, 8);
  240.                 PutLine();
  241.                 auditPtr = NULL;
  242.             }
  243.  
  244.             
  245.         }
  246.         return (auditPtr);
  247. }
  248.  
  249. void
  250. DumpAudit(
  251.         register AuditPtr        auditPtr
  252.     )
  253. {
  254.         register AuditQueueEntryPtr        queueEntryPtr;
  255.  
  256.         PutPascalString("\pAuditRecord version: ");
  257.         PutHexLeadingZeros((unsigned long) LOG.version.u.low, 4);
  258.         PutPascalString("\p low, ");
  259.         PutHexLeadingZeros((unsigned long) LOG.version.u.high, 4);
  260.         PutPascalString("\p high.");
  261.         PutLine();
  262.         PutPascalString("\pDebugging is ");
  263.         PutPascalString(((LOG.flags & kAuditEnabledMask)
  264.             ? "\penabled" : "\pdisabled"));
  265.         if (LOG.lostData == 0)
  266.             PutPascalString("\p, no lost data");
  267.         else {
  268.             PutUnsigned(LOG.lostData);
  269.             PutPascalString("\p lost data");
  270.         }
  271.         PutPascalString("\p, User refNum: ");
  272.         PutHexLeadingZeros((unsigned long) LOG.refNum, 8);
  273.         PutLine();
  274.         /*
  275.          * First dump all entries in the free queue.
  276.          */
  277.         PutPascalString("\pAudit area (already displayed)");
  278.         PutLine();
  279.         queueEntryPtr = (AuditQueueEntryPtr) LOG.free.queue.qHead;
  280.         if (queueEntryPtr != NULL) {
  281.             for (;;) {
  282.                 DumpAuditEntry(auditPtr, &queueEntryPtr->theEntry);
  283.                 if (queueEntryPtr == (AuditQueueEntryPtr) LOG.free.queue.qTail)
  284.                     break;
  285.                 queueEntryPtr = (AuditQueueEntryPtr) queueEntryPtr->qLink;
  286.             }
  287.         }
  288.         /*
  289.          * Then dump all entries in the data queue.
  290.          */
  291.         PutPascalString("\pAudit area (to be displayed)");
  292.         PutLine();
  293.         queueEntryPtr = (AuditQueueEntryPtr) LOG.data.queue.qHead;
  294.         if (queueEntryPtr != NULL) {
  295.             for (;;) {
  296.                 DumpAuditEntry(auditPtr, &queueEntryPtr->theEntry);
  297.                 if (queueEntryPtr == (AuditQueueEntryPtr) LOG.data.queue.qTail)
  298.                     break;
  299.                 queueEntryPtr = (AuditQueueEntryPtr) queueEntryPtr->qLink;
  300.             }
  301.         }
  302.         PutPascalString("\pEnd of Audit display");
  303.         PutLine();
  304. }
  305.  
  306. void
  307. DumpAuditEntry(
  308.         register AuditPtr            auditPtr,
  309.         register AuditEntryPtr        entryPtr
  310.     )
  311. {
  312.         Str255                        result;
  313.         
  314. #define DATA    (ENTRY.data)
  315.         if (ENTRY.tickCount != 0) {
  316.             FormatAuditEntryTimestamp(auditPtr, entryPtr, result);
  317.             PutPascalString(result);
  318.             PutPascalString("\p: ");
  319.             FormatAuditEntryData(entryPtr, result);
  320.             PutPascalString(result);
  321.             PutLine();
  322.         }
  323. #undef DATA
  324. }
  325.             
  326. /*
  327.  * Compare two strings. a is the keyword we're looking
  328.  * for: it is always specified in upper-case. b is
  329.  * the test string. It is case-converted. Note that
  330.  * this code presumes that the test words are in
  331.  * 7-bit ASCII.
  332.  */
  333. Boolean
  334. CompareString(
  335.         const StringPtr            a,
  336.         const StringPtr            b
  337.     )
  338. {
  339.         register short            i;
  340.         register unsigned char    c;
  341.         
  342.         if (a[0] != b[0])
  343.             return (FALSE);
  344.         else {
  345.             for (i = 1; i <= a[0]; i++) {
  346.                 c = b[i];
  347.                 if (c >= 'a' && c <= 'z')
  348.                     c -= ('a' - 'A');
  349.                 if (c != a[i])
  350.                     return (FALSE);
  351.             }
  352.             return (TRUE);
  353.         }
  354. }
  355.  
  356. /*
  357.  * Output an n-digit value with leading zeros.
  358.  */
  359. void
  360. PutUnsignedLeadingZeros(
  361.         unsigned long        value,
  362.         short                digits
  363.     )
  364. {
  365.         if (--digits > 0)
  366.             PutUnsignedLeadingZeros(value / 10, digits);
  367.         PutChar((value % 10) + '0');
  368. }
  369.  
  370. /*
  371.  * Output a signed decimal longword.
  372.  */
  373. void
  374. PutSigned(
  375.         signed long            value
  376.     )
  377. {
  378.         if (value < 0) {
  379.             PutChar('-');
  380.             value = (-value);
  381.         }
  382.         PutUnsigned((unsigned long) value);
  383. }
  384.  
  385. /*
  386.  * Output an unsigned decimal longword.
  387.  */
  388. void
  389. PutUnsigned(
  390.         unsigned long        value
  391.     )
  392. {
  393.         if (value >= 10)
  394.             PutUnsigned(value / 10);
  395.         PutChar((value % 10) + '0');
  396. }
  397.  
  398. /*
  399.  * Output a string of hex digits with leading zeros.
  400.  */
  401. void
  402. PutHexLeadingZeros(
  403.         unsigned long        value,
  404.         short                digits
  405.     )
  406. {
  407.         if (--digits > 0)
  408.             PutHexLeadingZeros(value >> 4, digits);
  409.         value &= 0x0F;
  410.         PutChar((value < 10)
  411.                 ? value + '0'
  412.                 : (value + ('A' - 10))
  413.             );
  414. }
  415.  
  416. /*
  417.  * Output a 4-byte character string. Unknown
  418.  * bytes (characters outside the range ' ' to '~')
  419.  * are replaced as '.'.
  420.  */
  421. void
  422. PutOSType(
  423.         OSType                    datum
  424.     )
  425. {
  426.         char                    value[sizeof (OSType)];
  427.         register short            i;
  428.         register unsigned char    c;
  429.         
  430.         BlockMove(&datum, value, sizeof (OSType));
  431.         PutChar('\'');
  432.         for (i = 0; i < sizeof (OSType); i++) {
  433.             c = value[i];
  434.             if (c < ' ' || c >= 0x7F)
  435.                 c = '.';
  436.             PutChar(c);
  437.         }
  438.         PutChar('\'');
  439. }
  440.  
  441. void
  442. PutPascalString(
  443.         const StringPtr            datum
  444.     )
  445. {
  446.         dcmdDrawString(datum);
  447. }
  448.  
  449.  
  450. void
  451. PutChar(
  452.         unsigned char            datum
  453.     )
  454. {
  455.         char            work[1];
  456.         
  457.         if (datum == '\n')
  458.             PutLine();
  459.         else {
  460.             work[0] = datum;
  461.             dcmdDrawText((StringPtr) work, sizeof (char));
  462.         }
  463. }
  464.  
  465. void
  466. PutLine(void)
  467. {
  468.         dcmdDrawLine("\p");
  469. }
  470.